#include "include/NativeLicense.h"
#include <jni.h>
#include <string>
#include <android/log.h>
#include <android/asset_manager_jni.h>
#include <android/asset_manager.h>
#include <vector>
#include <fstream>
// extern "C"
// {
//     void _init(void){};
//     int const dummy_to_make_this_compressible[10000] = {1, 2, 3};
// };

// 声明
static char licensePrivateSecretKey[] = "MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAmvxy8egEYreqLQnmSCIqKj3rDytXBlwBSNF/XPjHITR8/xEuPXCTOggYre9iQtqb1GRdn0Zn8qVT6nBxDIDhywIDAQABAkBVBYhJDG7beMXyTyv1Bkj7Q1xfxfbHllFeEQ89gXw7yiLIauqeJ/3ck+1tXtHS/MNUJMQ11WejMYjBvG5oCfyBAiEA5Y9eovBQ8cKffqLrOgUIzHnbK873OKwqjwoVg6GhG+8CIQCs1kAjGtyrHjBc96zHY20qQ1m9h6rqg7VblQK+rKpr5QIgR/wwWfnv+A/mwehGyRfhDXW807z/60aZxecMng1mHwMCIQCV8sNuMW3lX6mh3pcd3VrmYcxHrJ5SG7aKH/tjpbWtKQIgSZLGNdeOsV2EUWPUd/dCYaCnGZF79rlr3pWeRvSutGU=";
static char aceKey[] = "0nBxros6jjRnn2AJcobJWA==";
static bool isLicenseValid = false;
jboolean eval_decode_file(JNIEnv *env, jobject webView, std::vector<char> buffer)
{
    // 使用私钥解密数据,分段解密
    try
    {
        // 解密数据
        // java --
        // Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

        jclass cipherClass = env->FindClass("javax/crypto/Cipher");
        jmethodID getInstanceMethod2 = env->GetStaticMethodID(cipherClass, "getInstance", "(Ljava/lang/String;)Ljavax/crypto/Cipher;");
        jstring algorithm2 = env->NewStringUTF("AES/CBC/PKCS5Padding");
        jobject cipher = env->CallStaticObjectMethod(cipherClass, getInstanceMethod2, algorithm2);

        jclass secretKeySpecClass = env->FindClass("javax/crypto/spec/SecretKeySpec");
        jmethodID secretKeySpecConstructor = env->GetMethodID(secretKeySpecClass, "<init>", "([BLjava/lang/String;)V");
        // ace 使用java base64 解码为字节数组
        jclass base64Class = env->FindClass("android/util/Base64");
        jmethodID decodeMethod = env->GetStaticMethodID(base64Class, "decode", "(Ljava/lang/String;I)[B");
        jint flag = 2; // 表示使用 Base64.NO_WRAP 标志
        // aceKey 转java string
        jstring aceKeyStr = env->NewStringUTF(aceKey);
        jbyteArray aceKeyBytes = (jbyteArray)env->CallStaticObjectMethod(base64Class, decodeMethod, aceKeyStr, flag);

        jstring algorithm3 = env->NewStringUTF("AES");
        jobject keySpec = env->NewObject(secretKeySpecClass, secretKeySpecConstructor, aceKeyBytes, algorithm3);

        // cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
        jmethodID initMethod = env->GetMethodID(cipherClass, "init", "(ILjava/security/Key;Ljava/security/spec/AlgorithmParameterSpec;)V");
        jmethodID doFinalMethod = env->GetMethodID(cipherClass, "doFinal", "([B)[B");
        // IvParameterSpec ivParameterSpec = new IvParameterSpec("0133466789ffcdef".getBytes());
        jclass ivParameterSpecClass = env->FindClass("javax/crypto/spec/IvParameterSpec");
        jmethodID ivParameterSpecConstructor = env->GetMethodID(ivParameterSpecClass, "<init>", "([B)V");
        // jstring ivStr = env->NewStringUTF("0F102C9F71063130");
        char iv[] = {48, 70, 49, 48, 50, 67, 57, 70, 55, 49, 48, 54, 51, 49, 51, 48};
        jbyteArray ivBytes = env->NewByteArray(16);
        env->SetByteArrayRegion(ivBytes, 0, 16, reinterpret_cast<const jbyte *>(iv));
        jobject ivParameterSpec = env->NewObject(ivParameterSpecClass, ivParameterSpecConstructor, ivBytes);
        env->CallVoidMethod(cipher, initMethod, 2, keySpec, ivParameterSpec);
        // buffer 转换为 jbyteArray
        __android_log_print(ANDROID_LOG_INFO, "NativeLicense", "Encrypted data length: %lu", buffer.size());
        // 获取buffer的后4个字节
        std::vector<char> bufferEnd(buffer.end() - 4, buffer.end());
        int l = 0;
        for (int i = 0; i < 4; i++)
        {
            l = (l << 8) | (static_cast<unsigned char>(bufferEnd[i]));
        }
        __android_log_print(ANDROID_LOG_INFO, "NativeLicense", "plain text data length: %d", l);

        jbyteArray bufferBytes = env->NewByteArray(buffer.size() - 4);
        env->SetByteArrayRegion(bufferBytes, 0, buffer.size() - 4, reinterpret_cast<const jbyte *>(buffer.data()));
        jbyteArray decryptedData = (jbyteArray)env->CallObjectMethod(cipher, doFinalMethod, bufferBytes);
        // 解密后的数据转换为java字符串
        jsize length = env->GetArrayLength(decryptedData);
        jbyte *bytes = env->GetByteArrayElements(decryptedData, NULL);
        char *cString = new char[l + 1];
        std::memcpy(cString, bytes, l);
        cString[l] = '\0';
        // 根据长度l截取字节数组
        // jbyteArray bufferBytes2 = env->NewByteArray(l + 1);
        // env->SetByteArrayRegion(bufferBytes2, 0, l, reinterpret_cast<const jbyte *>(bytes));
        // // 填充最后一位\0
        // jbyte nullTerminator = '\0';
        // env->SetByteArrayRegion(bufferBytes2, l, 1, &nullTerminator);

        jstring jsContent = env->NewStringUTF(cString);
        // 调用java  webView.getEngine().evaluateJavascript(jsContent, null);
        // webview 接口org.apache.cordova.CordovaWebView
        jclass webViewClass = env->FindClass("org/apache/cordova/CordovaWebView");
        // jmethodID getEngineMethod = env->GetMethodID(webViewClass, "getEngine", "()Lorg/apache/cordova/engine/SystemWebViewEngine;");
        // getEngine org.apache.cordova.CordovaWebViewEngine
        jmethodID getEngineMethod = env->GetMethodID(webViewClass, "getEngine", "()Lorg/apache/cordova/CordovaWebViewEngine;");
        jobject engine = env->CallObjectMethod(webView, getEngineMethod);
        jclass engineClass = env->GetObjectClass(engine);
        jmethodID evaluateJavascriptMethod = env->GetMethodID(engineClass, "evaluateJavascript", "(Ljava/lang/String;Landroid/webkit/ValueCallback;)V");
        env->CallVoidMethod(engine, evaluateJavascriptMethod, jsContent, NULL);
        env->ReleaseByteArrayElements(decryptedData, bytes, JNI_ABORT);
        return JNI_TRUE;
    }
    catch (...)
    {
        __android_log_print(ANDROID_LOG_ERROR, "NativeLicense", "Exception occurred while decrypting RSA license");
        return JNI_FALSE;
    }
};

jboolean genRsaLicense(
    JNIEnv *env,
    jclass /* this */,
    jstring publicKeyStr,
    jstring content,
    jstring path)
{
    const char *contentCStr = env->GetStringUTFChars(content, NULL);
    const char *pathCStr = env->GetStringUTFChars(path, NULL);
    try
    {
        // 将 Base64 编码的公钥字符串解码为字节数组
        jclass base64Class = env->FindClass("android/util/Base64");
        jmethodID decodeMethod = env->GetStaticMethodID(base64Class, "decode", "(Ljava/lang/String;I)[B");
        jint flag = 2; // 表示使用 Base64.NO_WRAP 标志
        jbyteArray publicKeyBytes = (jbyteArray)env->CallStaticObjectMethod(base64Class, decodeMethod, publicKeyStr, flag);
        jthrowable exception = env->ExceptionOccurred();
        if (exception)
        {
            env->ExceptionClear();
            __android_log_print(ANDROID_LOG_ERROR, "NativeLicense", "Failed to decode public key");
            return JNI_FALSE;
        }
        // 获取公钥对象
        jclass keyFactoryClass = env->FindClass("java/security/KeyFactory");
        jmethodID getInstanceMethod = env->GetStaticMethodID(keyFactoryClass, "getInstance", "(Ljava/lang/String;)Ljava/security/KeyFactory;");
        jstring algorithm = env->NewStringUTF("RSA");
        jobject rsaKeyFactory = env->CallStaticObjectMethod(keyFactoryClass, getInstanceMethod, algorithm);
        jclass x509KeySpecClass = env->FindClass("java/security/spec/X509EncodedKeySpec");
        jmethodID x509KeySpecConstructor = env->GetMethodID(x509KeySpecClass, "<init>", "([B)V");
        jobject publicKeySpec = env->NewObject(x509KeySpecClass, x509KeySpecConstructor, publicKeyBytes);
        jmethodID generatePublicMethod = env->GetMethodID(keyFactoryClass, "generatePublic", "(Ljava/security/spec/KeySpec;)Ljava/security/PublicKey;");
        jobject publicKey = env->CallObjectMethod(rsaKeyFactory, generatePublicMethod, publicKeySpec);

        // 加密数据
        jclass cipherClass = env->FindClass("javax/crypto/Cipher");
        jmethodID getInstanceMethod2 = env->GetStaticMethodID(cipherClass, "getInstance", "(Ljava/lang/String;)Ljavax/crypto/Cipher;");
        jstring algorithm2 = env->NewStringUTF("RSA/ECB/PKCS1Padding");
        jobject cipher = env->CallStaticObjectMethod(cipherClass, getInstanceMethod2, algorithm2);
        jmethodID initMethod = env->GetMethodID(cipherClass, "init", "(ILjava/security/Key;)V");
        jmethodID doFinalMethod = env->GetMethodID(cipherClass, "doFinal", "([B)[B");
        env->CallVoidMethod(cipher, initMethod, 1, publicKey);

        // 将内容字符串转换为字节数组
        jstring contentStr = env->NewStringUTF(contentCStr);
        jbyteArray contentBytes = env->NewByteArray(env->GetStringLength(contentStr));
        env->SetByteArrayRegion(contentBytes, 0, env->GetStringLength(contentStr), reinterpret_cast<const jbyte *>(contentCStr));

        // 加密数据
        jbyteArray encryptedData = (jbyteArray)env->CallObjectMethod(cipher, doFinalMethod, contentBytes);
        __android_log_print(ANDROID_LOG_INFO, "NativeLicense", "Encrypted data length: %d", env->GetArrayLength(encryptedData));
        // 写入文件
        jsize length = env->GetArrayLength(encryptedData);
        jbyte *bytes = env->GetByteArrayElements(encryptedData, NULL);
        std::ofstream ofs(pathCStr, std::ios::binary);
        ofs.write(reinterpret_cast<char *>(bytes), length);
        ofs.close();
        __android_log_print(ANDROID_LOG_INFO, "NativeLicense", "License file written to %s", pathCStr);
        // 释放资源
        env->ReleaseByteArrayElements(encryptedData, bytes, JNI_ABORT);
        env->ReleaseStringUTFChars(content, contentCStr);
        env->ReleaseStringUTFChars(path, pathCStr);
        return JNI_TRUE;
    }
    catch (...)
    {
        __android_log_print(ANDROID_LOG_ERROR, "NativeLicense", "Exception occurred while generating RSA license");
        env->ReleaseStringUTFChars(content, contentCStr);
        env->ReleaseStringUTFChars(path, pathCStr);
    }
    return JNI_FALSE;
}

JNIEXPORT jboolean JNICALL Java_com_runyu_cordova_plugin_crypto_NativeLicense_checkLicense(JNIEnv *env, jclass jc, jobject manager, jobject applicationContext)
{
    // 读取许可证文件
    jclass contextClass = env->FindClass("android/content/Context");
    jmethodID getCodeCacheDirMethod = env->GetMethodID(contextClass, "getCodeCacheDir", "()Ljava/io/File;");
    if (getCodeCacheDirMethod == NULL)
    {
        __android_log_print(ANDROID_LOG_ERROR, "NativeLicense", "Failed to find getCodeCacheDir method");
        return JNI_FALSE;
    }

    // 获取绝对路径的 File 对象
    jobject fileObj = env->CallObjectMethod(applicationContext, getCodeCacheDirMethod);
    jclass fileClass = env->FindClass("java/io/File");
    jmethodID getAbsolutePathMethod = env->GetMethodID(fileClass, "getAbsolutePath", "()Ljava/lang/String;");
    if (getAbsolutePathMethod == NULL)
    {
        __android_log_print(ANDROID_LOG_ERROR, "NativeLicense", "Failed to find getAbsolutePath method");
        return JNI_FALSE;
    }
    jstring absolutePath = (jstring)env->CallObjectMethod(fileObj, getAbsolutePathMethod);
    const char *absolutePathCStr = env->GetStringUTFChars(absolutePath, NULL);
    // 进行字符串连接
    std::string licenseFilePathStr = std::string(absolutePathCStr) + "/license.lic";
    // 释放 C 字符串
    env->ReleaseStringUTFChars(absolutePath, absolutePathCStr);
    // 读取许可证文件
    std::ifstream ifs(licenseFilePathStr, std::ios::binary);
    if (!ifs)
    {
        __android_log_print(ANDROID_LOG_ERROR, "NativeLicense", "Failed to open license file");
        return JNI_FALSE;
    }
    std::vector<char> buffer((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());
    ifs.close();
    // 使用私钥解密数据
    try
    {
        // 将 Base64 编码的私钥字符串解码为字节数组
        jclass base64Class = env->FindClass("android/util/Base64");
        jmethodID decodeMethod = env->GetStaticMethodID(base64Class, "decode", "(Ljava/lang/String;I)[B");
        jint flag = 2; // 表示使用 Base64.NO_WRAP 标志
        // licensePrivateSecretKey 转java string
        jstring licensePrivateSecretKeyStr = env->NewStringUTF(licensePrivateSecretKey);
        jbyteArray privateKeyBytes = (jbyteArray)env->CallStaticObjectMethod(base64Class, decodeMethod, licensePrivateSecretKeyStr, flag);
        // 获取私钥对象
        jclass keyFactoryClass = env->FindClass("java/security/KeyFactory");
        jmethodID getInstanceMethod = env->GetStaticMethodID(keyFactoryClass, "getInstance", "(Ljava/lang/String;)Ljava/security/KeyFactory;");
        jstring algorithm = env->NewStringUTF("RSA");
        jobject rsaKeyFactory = env->CallStaticObjectMethod(keyFactoryClass, getInstanceMethod, algorithm);
        jclass pkcs8KeySpecClass = env->FindClass("java/security/spec/PKCS8EncodedKeySpec");
        jmethodID pkcs8KeySpecConstructor = env->GetMethodID(pkcs8KeySpecClass, "<init>", "([B)V");
        jobject privateKeySpec = env->NewObject(pkcs8KeySpecClass, pkcs8KeySpecConstructor, privateKeyBytes);
        jmethodID generatePrivateMethod = env->GetMethodID(keyFactoryClass, "generatePrivate", "(Ljava/security/spec/KeySpec;)Ljava/security/PrivateKey;");
        jobject privateKey = env->CallObjectMethod(rsaKeyFactory, generatePrivateMethod, privateKeySpec);

        // 解密数据
        jclass cipherClass = env->FindClass("javax/crypto/Cipher");
        jmethodID getInstanceMethod2 = env->GetStaticMethodID(cipherClass, "getInstance", "(Ljava/lang/String;)Ljavax/crypto/Cipher;");
        jstring algorithm2 = env->NewStringUTF("RSA/ECB/PKCS1Padding");
        jobject cipher = env->CallStaticObjectMethod(cipherClass, getInstanceMethod2, algorithm2);
        jmethodID initMethod = env->GetMethodID(cipherClass, "init", "(ILjava/security/Key;)V");
        jmethodID doFinalMethod = env->GetMethodID(cipherClass, "doFinal", "([B)[B");
        env->CallVoidMethod(cipher, initMethod, 2, privateKey);
        // buffer 转换为 jbyteArray
        jbyteArray bufferBytes = env->NewByteArray(buffer.size());
        env->SetByteArrayRegion(bufferBytes, 0, buffer.size(), reinterpret_cast<const jbyte *>(buffer.data()));
        jbyteArray decryptedData = (jbyteArray)env->CallObjectMethod(cipher, doFinalMethod, bufferBytes);
        // 解密后的数据转换为java字符串
        jsize length = env->GetArrayLength(decryptedData);
        jbyte *bytes = env->GetByteArrayElements(decryptedData, NULL);
        std::string decryptedDataStr = std::string(reinterpret_cast<char *>(bytes), length);
        env->ReleaseByteArrayElements(decryptedData, bytes, JNI_ABORT);
        // 检查解密后的数据
        // 使用manager对象调用listBarcodeDevices方法
        jclass aidcManagerClass = env->FindClass("com/honeywell/aidc/AidcManager");
        jmethodID listBarcodeDevicesMethod = env->GetMethodID(aidcManagerClass, "listBarcodeDevices", "()Ljava/util/List;");
        jobject listBarcodeDevices = env->CallObjectMethod(manager, listBarcodeDevicesMethod);
        jclass listClass = env->GetObjectClass(listBarcodeDevices);
        jmethodID sizeMethod = env->GetMethodID(listClass, "size", "()I");
        jint size = env->CallIntMethod(listBarcodeDevices, sizeMethod);
        if (size > 0)
        {
            // 获取第一个 BarcodeReaderInfo 对象
            jmethodID getMethod = env->GetMethodID(listClass, "get", "(I)Ljava/lang/Object;");
            jobject barcodeReaderInfo = env->CallObjectMethod(listBarcodeDevices, getMethod, 0);

            // 获取 Scanner Serial Number
            jclass barcodeReaderInfoClass = env->FindClass("com/honeywell/aidc/BarcodeReaderInfo");
            jmethodID getScannerSerialNumberMethod = env->GetMethodID(barcodeReaderInfoClass, "getScannerSerialNumber", "()Ljava/lang/String;");
            jstring scannerSerialNumber = (jstring)env->CallObjectMethod(barcodeReaderInfo, getScannerSerialNumberMethod);
            // 检查解密后的数据是否与 Scanner Serial Number 相等
            if (decryptedDataStr == env->GetStringUTFChars(scannerSerialNumber, NULL))
            {
                isLicenseValid = true;
                return JNI_TRUE;
            }
        }
        return JNI_FALSE;
    }
    catch (...)
    {
        __android_log_print(ANDROID_LOG_ERROR, "NativeLicense", "Exception occurred while decrypting RSA license");
        return JNI_FALSE;
    }

    return JNI_FALSE;
};

JNIEXPORT jboolean JNICALL Java_com_runyu_cordova_plugin_crypto_NativeLicense_subjectLicense(JNIEnv *env, jclass jc, jobject manager, jobject applicationContext, jstring key)
{
    // 获取 AidcManager 类
    jclass aidcManagerClass = env->FindClass("com/honeywell/aidc/AidcManager");
    if (aidcManagerClass == NULL)
    {
        __android_log_print(ANDROID_LOG_ERROR, "NativeLicense", "Failed to find AidcManager class");
        return JNI_FALSE;
    }

    // 获取 listBarcodeDevices 方法
    jmethodID listBarcodeDevicesMethod = env->GetMethodID(aidcManagerClass, "listBarcodeDevices", "()Ljava/util/List;");
    if (listBarcodeDevicesMethod == NULL)
    {
        __android_log_print(ANDROID_LOG_ERROR, "NativeLicense", "Failed to find listBarcodeDevices method");
        return JNI_FALSE;
    }

    // 获取 Application Context 对象的 getCodeCacheDir 方法
    jclass contextClass = env->FindClass("android/content/Context");
    jmethodID getCodeCacheDirMethod = env->GetMethodID(contextClass, "getCodeCacheDir", "()Ljava/io/File;");
    if (getCodeCacheDirMethod == NULL)
    {
        __android_log_print(ANDROID_LOG_ERROR, "NativeLicense", "Failed to find getCodeCacheDir method");
        return JNI_FALSE;
    }

    // 获取绝对路径的 File 对象
    jobject fileObj = env->CallObjectMethod(applicationContext, getCodeCacheDirMethod);
    jclass fileClass = env->FindClass("java/io/File");
    jmethodID getAbsolutePathMethod = env->GetMethodID(fileClass, "getAbsolutePath", "()Ljava/lang/String;");
    if (getAbsolutePathMethod == NULL)
    {
        __android_log_print(ANDROID_LOG_ERROR, "NativeLicense", "Failed to find getAbsolutePath method");
        return JNI_FALSE;
    }
    jstring absolutePath = (jstring)env->CallObjectMethod(fileObj, getAbsolutePathMethod);
    const char *absolutePathCStr = env->GetStringUTFChars(absolutePath, NULL);
    // 进行字符串连接
    std::string licenseFilePathStr = std::string(absolutePathCStr) + "/license.lic";
    // 释放 C 字符串
    env->ReleaseStringUTFChars(absolutePath, absolutePathCStr);
    // 将 C++ 字符串转换为 Java 字符串
    jstring licenseFilePath = env->NewStringUTF(licenseFilePathStr.c_str());
    // 获取 Scanner Serial Number
    jobject listBarcodeDevices = env->CallObjectMethod(manager, listBarcodeDevicesMethod);
    jclass listClass = env->GetObjectClass(listBarcodeDevices);
    jmethodID sizeMethod = env->GetMethodID(listClass, "size", "()I");
    jint size = env->CallIntMethod(listBarcodeDevices, sizeMethod);
    if (size > 0)
    {
        // 获取第一个 BarcodeReaderInfo 对象
        jmethodID getMethod = env->GetMethodID(listClass, "get", "(I)Ljava/lang/Object;");
        jobject barcodeReaderInfo = env->CallObjectMethod(listBarcodeDevices, getMethod, 0);

        // 获取 Scanner Serial Number
        jclass barcodeReaderInfoClass = env->FindClass("com/honeywell/aidc/BarcodeReaderInfo");
        jmethodID getScannerSerialNumberMethod = env->GetMethodID(barcodeReaderInfoClass, "getScannerSerialNumber", "()Ljava/lang/String;");
        jstring scannerSerialNumber = (jstring)env->CallObjectMethod(barcodeReaderInfo, getScannerSerialNumberMethod);
        // // 调用 genRsaLicense 方法生成许可证文件
        jboolean r = genRsaLicense(env, jc, key, scannerSerialNumber, licenseFilePath);
        if (r)
        {
            isLicenseValid = true;
        }
        return r;
    }

    return JNI_TRUE;
};

JNIEXPORT jboolean JNICALL Java_com_runyu_cordova_plugin_crypto_NativeLicense_startApp(JNIEnv *env, jclass jc, jobject webView, jobject applicationContext)
{
    if (!isLicenseValid)
    {
        __android_log_print(ANDROID_LOG_ERROR, "NativeLicense", "startApp memory License is not valid");
        return JNI_FALSE;
    }
    // 获取 Application Context 对象js的文件夹位置 assets/www/data/目录下所有的.d结尾的文件

    try
    {
        jclass contextClass = env->GetObjectClass(applicationContext);
        if (contextClass == nullptr)
        {
            __android_log_print(ANDROID_LOG_ERROR, "NativeLicense", "startApp Failed to get context class");
            // 处理错误
            return JNI_FALSE;
        }

        // 获取 getAssets 方法的 ID
        jmethodID getAssetsMethodID = env->GetMethodID(contextClass, "getAssets", "()Landroid/content/res/AssetManager;");
        if (getAssetsMethodID == nullptr)
        {
            __android_log_print(ANDROID_LOG_ERROR, "NativeLicense", "startApp Failed to get getAssets method ID");
            // 处理错误
            return JNI_FALSE;
        }

        // 调用 getAssets 方法获取 AssetManager 对象
        jobject jassetManager = env->CallObjectMethod(applicationContext, getAssetsMethodID);
        if (jassetManager == nullptr)
        {
            __android_log_print(ANDROID_LOG_ERROR, "NativeLicense", "startApp Failed to get asset manager");
            // 处理错误
            return JNI_FALSE;
        }
        __android_log_print(ANDROID_LOG_INFO, "NativeLicense", "startApp Got asset manager");
        AAssetManager *assetManager = AAssetManager_fromJava(env, jassetManager);
        // 打开目录
        AAssetDir *dir = AAssetManager_openDir(assetManager, "www/data");
        if (dir == nullptr)
        {
            __android_log_print(ANDROID_LOG_ERROR, "NativeLicense", "Failed to open directory www/data");
            // 处理错误
            return JNI_FALSE;
        }

        __android_log_print(ANDROID_LOG_INFO, "NativeLicense", "startApp Opened directory www/data");
        // 遍历目录下的文件
        const char *filename = nullptr;
        while ((filename = AAssetDir_getNextFileName(dir)) != nullptr)
        {
            // log
            __android_log_print(ANDROID_LOG_INFO, "NativeLicense", "startApp get filename: %s", filename);
            // 检查文件是否以指定的扩展名结尾
            std::string filenameStr(filename);
            if (filenameStr.length() >= strlen(".d") && filenameStr.substr(filenameStr.length() - strlen(".d")) == ".d")
            {
                filenameStr = "www/data/" + filenameStr;
                __android_log_print(ANDROID_LOG_INFO, "NativeLicense", "get .d file : %s", filenameStr.c_str());
                AAsset *asset = AAssetManager_open(assetManager, filenameStr.c_str(), AASSET_MODE_BUFFER);
                if (asset == nullptr)
                {
                    __android_log_print(ANDROID_LOG_ERROR, "NativeLicense", "Failed to open asset %s", filenameStr.c_str());
                    return JNI_FALSE;
                }
                // 读取文件内容
                const void *data = AAsset_getBuffer(asset);
                off_t length = AAsset_getLength(asset);
                std::vector<char> buffer((const char *)data, (const char *)data + length);
                AAsset_close(asset);
                // 解密文件内容
                jboolean evalResult = eval_decode_file(env, webView, buffer);
                if (!evalResult)
                {
                    return JNI_FALSE;
                }
            }
        }

        // 关闭目录
        AAssetDir_close(dir);
    }
    catch (...)
    {
        __android_log_print(ANDROID_LOG_ERROR, "NativeLicense", "Exception occurred while starting app");
        return JNI_FALSE;
    }

    return JNI_TRUE;
};
